﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GJLib.inernal;
using Newtonsoft.Json;
using System.IO;

namespace GJLib
{
    public class BigSixNineHelpVer2
    {

        Dictionary<String, bool> _jiDayNight = null;
        List<String> _天將 = null;

        public String 貴人算法 = "";


        public void cal行年(BigSixNinePan pan, String 本命, bool male)
        {
            pan.行年 = "";
            if (pan.占課四柱.yearGj.干支 == null)

                return;
            String 行年 = GJR.行年(本命, pan.占課四柱.yearGj.干支, male);
            pan.行年 = 行年;
        }
        public BigSixNineHelpVer2()
        {
            loadDaynight();
            LoadGweiRen();
        }
        protected void LoadGweiRen()
        {
            String fileName = @"D:\project\五術\data\relation\GweiRen.json";
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            _天將 = JsonConvert.DeserializeObject<List<String>>(content);
        }
        protected void loadDaynight()
        {
            String fileName = @"D:\project\五術\data\relation" + "\\" + "jiDayNight.json";
            String content = File.ReadAllText(fileName, Encoding.UTF8);
            _jiDayNight = JsonConvert.DeserializeObject<Dictionary<String, bool>>(content);
        }
        protected bool isDay(String ji)
        {
            if (ji.Length > 1)
                ji = ji.Substring(1, 1);
            return _jiDayNight[ji];
        }


        public void selfCheck()
        {
            var c = File.ReadAllText(@"D:\project\五術\data\trans3\trans3.json");
            Dictionary<String, Dictionary<String, List<String>>> table = JsonConvert.DeserializeObject<Dictionary<String, Dictionary<String, List<String>>>>(c);
            foreach (var p in table.Keys)
            {
                var t = table[p];
                foreach (var ji in t.Keys)
                {
                    var bp = prepareby干上(p, ji);
                    String trans3 = t[ji][0];
                    if (trans3.Equals(bp.get三傳()) == false)
                    {
                        String r = String.Format("{0} 日 干上{1} = {2} 算出來 {3}  {4} ", p, ji, trans3, bp.get三傳(), t[ji][1]);
                        System.Diagnostics.Debug.WriteLine(r);
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine("Check Complete!");
        }

        public BigSixNinePan prepare(String 年干支, String 月干支, String 日干支, String 時干支, String 月將)
        {
            if (月干支.Length == 1)
            {
                月干支 = GJR.五虎遁(GJR.pickFirstWord(年干支), 月干支);
            }
            if (時干支.Length == 1)
            {
                時干支 = GJR.五鼠遁(GJR.pickFirstWord(日干支), 時干支);
            }

            return null;
        }

        public void updateBy時支(BigSixNinePan pan, String ji)
        {
            String up = pan.取上神("子");
            int off = (GJR.JiId(up) - 1+12)%12;
            int tid = GJR.JiId(GJR.pickLastWord(ji));
            int mid = (off + tid) % 12;
            //off = 月將-時支
            //月將=off+ 時支
            String 月將=GJR.Id2Ji(mid);
            String 時干支=GJR.五鼠遁(pan.日干, ji);
            pan.占課四柱.hourGj.干支 = 時干支;
            pan.月將 = 月將;
            process天將(pan);            
        }

        public void updateBy月將(BigSixNinePan pan, String mongeneral)
        {
            String up = pan.取上神("子");
            int off = (GJR.JiId(up) - 1 + 12) % 12;
            int mid = GJR.JiId(mongeneral);
            int jid = (mid - off+12)%12;
            //off = 月將-時支
            //時支=月將-off
            String 時支=GJR.Id2Ji(jid);
            String 時干支 = GJR.五鼠遁(pan.日干, 時支);
            pan.月將 = mongeneral;
            pan.占課四柱.hourGj.干支 = 時干支;
            process天將(pan);            

        }
        
        public BigSixNinePan prepare(DateTime dt, String ji)
        {
            int id = GJR.JiId(ji);
            id = id * 12 - 2;
            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, id, dt.Second);
            return prepare(dt);
        }

        public BigSixNinePan prepare(DateTime dt)
        {
            //算出月將
            int hr = dt.Hour;
            List<String> p4 = GanJiHelper.get4Pillar(dt);
            Pillar4 起課時間 = new Pillar4();
            起課時間.datetime = dt;
            起課時間.setGj(p4);
            String 月將 = JachiHelper.getMonthGeneral(dt);
            BigSixNinePan pan69 = new BigSixNinePan();
            pan69.setPillar(起課時間);
            pan69.月將 = 月將;
            prepare(起課時間.dayGj.干支, 起課時間.hourGj.支, 月將, pan69);
            return pan69;
        }

        protected List<String> prepareSkyBy干上(String 日干, String 干上)
        {

            日干 = GJR.pickFirstWord(日干);
            String ji = GJR.天干寄宮(日干);
            int pos = GJR.JiId(ji);
            int start = GJR.JiId(干上);
            List<String> sky = new List<string>();
            for (int i = 0; i < 12; i++)
                sky.Add("");
            for (int i = 0; i < 12; i++)
            {
                sky[(pos + i) % 12] = GJR.Id2Ji(start + i);
            }
            return sky;
        }
        public BigSixNinePan prepareby干上(String 日干支, String 干上, BigSixNinePan pan69 = null)
        {
            /*
            int idto = GJR.JiId(干上);
            int idfrom = GJR.JiId(ji);
            int off = idto - idfrom;
            if (off < 0)
                off += 12;
             String mong = GJR.Id2Ji(1 + off);
             return prepare(日干支, "子", mong, pan69);
            */
            if (pan69 == null)
                pan69 = new BigSixNinePan();

            Dictionary<String, String> note = new Dictionary<string, string>();
            List<String> sky = prepareSkyBy干上(日干支, 干上);
            List<String> class4 = calClass4Easy(日干支, sky);
            pan69.日干支 = 日干支;
            pan69.setKeyPan(sky);
            pan69.setClass4(class4);
            process三傳(pan69);
            process三傳六親(pan69);
            process三傳遁干(pan69);
            process天將(pan69);
            prepareOtherOption(pan69.占課四柱.yearGj.干支,
                                       pan69.占課四柱.monthGj.干支,
                                       pan69.占課四柱.dayGj.干支,
                                       pan69.占課四柱.hourGj.干支,
                                       pan69.options);
            prepareOtherOptions2(pan69);
            return pan69;
        }
        private void process天將(BigSixNinePan pan69)
        {
            update天將(pan69);
            update課傳天將(pan69);
        }  

        public BigSixNinePan prepare(String 日干支, String 時支, String 月將, BigSixNinePan pan69 = null)
        {
            if (pan69 == null)
                pan69 = new BigSixNinePan();

            Dictionary<String, String> note = new Dictionary<string, string>();

            List<String> sky = createSkySeq(時支, 月將);
            List<String> class4 = calClass4Easy(日干支, sky);

            pan69.日干支 = 日干支;
            pan69.時支 = 時支;
            pan69.setKeyPan(sky);
            pan69.setClass4(class4);
            process三傳(pan69);

            update天將(pan69);
            process三傳六親(pan69);
            
            prepareOtherOption(pan69.占課四柱.yearGj.干支,
                                                   pan69.占課四柱.monthGj.干支,
                                                   pan69.占課四柱.dayGj.干支,
                                                   pan69.占課四柱.hourGj.干支,
                                                   pan69.options);
            prepareOtherOptions2(pan69);

            return pan69;
        }
        private void prepareOtherOptions2(BigSixNinePan pan69)
        {
            if (pan69.options.ContainsKey("日空"))
            {
                String km = (String)pan69.options["日空"];
                String low = "";
                foreach (char c in km)
                {
                    low += pan69.取上神(String.Format("{0}", c));
                };
                if (String.IsNullOrWhiteSpace(low) == false)
                {
                    pan69.options.Add("陷落", low);
                }
            }
        }
        private void prepareOtherOption(String 年干支, String 月干支, String 日干支, String 時干支, Dictionary<String, Object> result)
        {
            if (時干支 != null)
            {
                bool isday = isDay(時干支);
                if (isday)
                    result.Add("占法", "晝占");
                else
                    result.Add("占法", "夜占");
                //陷落
                if (時干支.Contains("_") == false)
                    result.Add("時空", GJR.空亡(時干支));

            }

            result.Add("旬首", GJR.旬首(日干支));
            result.Add("旬丁", GJR.旬丁(日干支));
            result.Add("旬庚", GJR.旬庚(日干支));
            result.Add("旬辛", GJR.旬辛(日干支));
            result.Add("旬癸", GJR.旬癸(日干支));
            result.Add("六合", GJR.六合(日干支));
            result.Add("支沖", GJR.沖(日干支));
            result.Add("日德", GJR.日德(日干支));
            result.Add("支德", GJR.支德(日干支));
            result.Add("天馬", GJR.天馬(日干支));
            result.Add("驛馬", GJR.驛馬(日干支));
            result.Add("桃花", GJR.桃花(日干支));
            result.Add("支刑", GJR.A刑B(日干支));
            result.Add("支破", GJR.支破(日干支));
            result.Add("干害", GJR.支害(GJR.天干寄宮(GJR.pickFirstWord(日干支))));
            result.Add("支害", GJR.支害(日干支));
            result.Add("日空", GJR.空亡(日干支));
            result.Add("三合", GJR.三合(日干支));

            if (月干支 != null)
                result.Add("月德", GJR.月德(月干支));

        }

        private bool isDirCounter(string groundStart)
        {
            int id = GJR.JiId(groundStart) % 12;
            if (id <= 5)
                return true;
            return false;
        }
        protected void update天將(BigSixNinePan pan69)
        {
            String 日干 = pan69.日干;
            String 時支 = pan69.時支;
            if (時支 == null)
                return;

            String 晝貴 = GJR.貴人晝占(日干, this.貴人算法);
            String 夜貴 = GJR.貴人夜占(日干, this.貴人算法);

            bool isday = isDay(時支);
            String skyStart = "";
            if (isday)
                skyStart = 晝貴;
            else
                skyStart = 夜貴;
            String 對地 = "";
            bool 貴人順行 = false;
            var 盤 = pan69.盤;
            foreach (var p in 盤)
            {
                if (p.天 == skyStart)
                {
                    對地 = p.地;
                    貴人順行 = isDirCounter(對地);
                    break;
                }
            }
            if (貴人順行)
                pan69.貴人順逆 = "順行";
            else
                pan69.貴人順逆 = "逆行";

            int gpos = GJR.JiId(對地);
            for (int i = 0; i < 12; i++)
            {
                int pos;
                if (貴人順行)
                    pos = ((gpos + i) + 12) % 12;
                else
                    pos = ((gpos - i) + 12) % 12;
                盤[pos].天將 = _天將[i];
            }
        }

        protected void process賊剋比用涉害(BigSixNinePan pan69)
        {
            var 賊課 = pan69.賊課();

            int idx = pick初傳From有剋(pan69, true);
            pan69.發用課 = idx;
            String ji = pan69.課[idx].上神;
            setup三傳from初傳(pan69, ji);
        }

        /***************************************************************************
         * @伏吟有 下賊上的 只有兩個 癸/乙
         * 癸-->一路丑到底,所以取刑,一定是丑戌未 (土刑為逆)
         * 
         * 
         ***************************************************************************/
        protected void process伏吟(BigSixNinePan pan69)
        {
            pan69.addTransNote("伏吟");
            String 日干 = pan69.日干;
            String 日支 = pan69.日支;
            Dictionary<String, Trans> 三傳 = pan69.三傳;
            if (日干.Equals("癸"))
            {
                pan69.addTransNote("不虞");
                pan69.addTransNote("元首");
                三傳["初傳"].支神 = "丑";
                三傳["中傳"].支神 = "戌";
                三傳["末傳"].支神 = "未";

                return;
            }
            if (日干.Equals("乙"))
            {
                pan69.addTransNote("杜傳");
                pan69.addTransNote("始入");
                三傳["初傳"].支神 = "辰";
                三傳["中傳"].支神 = 日支;
                String next = GJR.A刑B(日支);
                if (next.Equals(三傳["中傳"].支神) || next.Equals(三傳["初傳"].支神))
                    next = GJR.沖(三傳["中傳"].支神);
                三傳["末傳"].支神 = next;
                return;
            }
            bool 陽日 = GJR.陰陽(日干) == e陰陽.陽;

            if (陽日)
            {
                bool has自刑 = false;
                三傳["初傳"].支神 = pan69.取上神(GJR.天干寄宮(日干));
                String next = GJR.A刑B(三傳["初傳"].支神);
                if (next.Equals(三傳["初傳"].支神))
                {
                    next = pan69.取上神(日支);
                    has自刑 = true;
                }
                三傳["中傳"].支神 = next;
                next = GJR.A刑B(next);
                if (next.Equals(三傳["中傳"].支神) || next.Equals(三傳["初傳"].支神))
                {
                    has自刑 = true;
                    next = GJR.沖(next);
                }
                if (has自刑)
                    pan69.addTransNote("杜傳");
                else
                    pan69.addTransNote("自任");
                三傳["末傳"].支神 = next;
            }
            else
            {
                bool has自刑 = false;
                pan69.addTransNote("自信");
                三傳["初傳"].支神 = pan69.取上神(日支);
                String next = GJR.A刑B(三傳["初傳"].支神);
                if (next.Equals(三傳["初傳"].支神))
                {
                    next = pan69.取上神(GJR.天干寄宮(日干));
                    has自刑 = true;
                }
                三傳["中傳"].支神 = next;
                next = GJR.A刑B(三傳["中傳"].支神);
                if (next.Equals(三傳["中傳"].支神) || next.Equals(三傳["初傳"].支神))
                {
                    next = GJR.沖(三傳["中傳"].支神);
                    has自刑 = true;
                }
                if (has自刑)
                    pan69.addTransNote("杜傳");
                else
                    pan69.addTransNote("自信");
                三傳["末傳"].支神 = next;
            }
        }
        protected void process三傳(BigSixNinePan pan69)
        {
            int 賊剋數 = pan69.剋課().Count + pan69.賊課().Count;

            if (pan69.伏吟)
            {
                process伏吟(pan69);
                return;
            }
            if (pan69.返吟)
            {
                process返吟(pan69);
                return;
            }
            if (pan69.八專)
            {
                process八專(pan69, 賊剋數);
                return;
            }

            if (賊剋數 > 0)
            {
                process賊剋比用涉害(pan69);
                return;
            }
            if (process遙剋(pan69))
                return;

            bool 不備 = pan69.不備;

            if (不備 == false)
                process昂星(pan69);
            else
                process別責(pan69);



        }

        private void process別責(BigSixNinePan pan69)
        {
            pan69.addTransNote("別責");
            bool 陽日 = GJR.陰陽(pan69.日干) == e陰陽.陽;
            var 三傳 = pan69.三傳;
            var 日干 = pan69.日干;
            var 日支 = pan69.日支;
            var 日干寄宮 = GJR.天干寄宮(日干);
            if (陽日)
            {
                三傳["初傳"].支神 = pan69.取上神(GJR.天干寄宮(GJR.五合(日干)));
                三傳["中傳"].支神 = pan69.取上神(日干寄宮);
                三傳["末傳"].支神 = pan69.取上神(日干寄宮);
            }
            else
            {
                三傳["初傳"].支神 = GJR.三合前(日支);
                三傳["中傳"].支神 = pan69.取上神(日干寄宮);
                三傳["末傳"].支神 = pan69.取上神(日干寄宮);
            }

        }

        private void process昂星(BigSixNinePan pan69)
        {
            bool 陽日 = GJR.陰陽(pan69.日干) == e陰陽.陽;
            pan69.addTransNote("昂星");
            var 三傳 = pan69.三傳;
            if (陽日)
            {
                pan69.addTransNote("虎視");
                三傳["初傳"].支神 = pan69.取上神("酉");
                三傳["中傳"].支神 = pan69.取上神(pan69.日支);
                三傳["末傳"].支神 = pan69.取上神(GJR.天干寄宮(pan69.日干));
            }
            else
            {
                pan69.addTransNote("冬蛇掩目");
                三傳["初傳"].支神 = pan69.取下神("酉");
                三傳["中傳"].支神 = pan69.取上神(GJR.天干寄宮(pan69.日干));
                三傳["末傳"].支神 = pan69.取上神(pan69.日支);
            }
        }
        private bool process遙剋(BigSixNinePan pan69)
        {
            pan69.addTransNote("遙剋");
            //藁矢 天盤 喀 pan69.日干 
            List<int> 天盤剋日干 = new List<int>();
            List<int> 日干剋天盤 = new List<int>();
            for (int i = 0; i < 4; i++)
            {
                int k = GJR.A剋B(pan69.課[i].上神, pan69.日干);
                if (k > 0)
                    天盤剋日干.Add(i);
                if (k < 0)
                    日干剋天盤.Add(i);
            }
            //-----------------------------------
            if ((天盤剋日干.Count + 日干剋天盤.Count) == 0)
                return false;
            //-----------這裡又是一個點~~ 除掉了就保證
            if (pan69.is14同())
            {
                天盤剋日干.Remove(3);
                日干剋天盤.Remove(3);
            }
            if (pan69.is23同())
            {
                天盤剋日干.Remove(2);
                日干剋天盤.Remove(2);
            }
            if (天盤剋日干.Count > 0)
            {
                pan69.addTransNote("蒿矢");
                if (process遙剋_step2(pan69, 天盤剋日干))
                    return true;
            }
            if (日干剋天盤.Count > 0)
            {
                pan69.addTransNote("彈射");
                if (process遙剋_step2(pan69, 日干剋天盤))
                    return true;
            }
            return false;
        }

        protected void setup三傳from初傳(BigSixNinePan pan69, String ji)
        {
            var 三傳 = pan69.三傳;
            三傳["初傳"].支神 = ji;
            三傳["中傳"].支神 = pan69.取上神(三傳["初傳"].支神);
            三傳["末傳"].支神 = pan69.取上神(三傳["中傳"].支神);
        }
        protected bool process遙剋_step2(BigSixNinePan pan69, List<int> classIds)
        {
            int id = -1;
            if (classIds.Count == 1)
                id = classIds[0];
            else
            {
                pan69.addTransNote("比用");
                id = PickFromListBy比用(pan69, classIds);
            }
            if (id != -1)
            {
                pan69.發用課 = id;
                String ji = pan69.課[id].上神;
                setup三傳from初傳(pan69, ji);
                return true;
            }
            throw new Exception("取遙剋失敗:" + pan69.toJson());
        }
        private int PickFromListBy比用(BigSixNinePan pan69, List<int> classIds)
        {
            var 日陰陽 = GJR.陰陽(pan69.日干);
            var arr = (from idx in classIds where GJR.陰陽(pan69.課[idx].上神) == 日陰陽 select idx).ToList<int>();
            if (arr.Count == 1)
                return arr[0];
            return -1;
        }
        private void process八專(BigSixNinePan pan69, int 賊剋數)
        {
            pan69.addTransNote("八專");
            if (賊剋數 > 0)
            {
                process八專有剋(pan69);
            }
            else
            {
                process八專無剋(pan69);
                return;
            }
        }
        private void process八專有剋(BigSixNinePan pan69)
        {
            int idx = pick初傳From有剋(pan69);
            pan69.發用課 = idx;
            String 初傳 = pan69.課[idx].上神;
            setup三傳from初傳(pan69, 初傳);
        }
        private void process八專無剋(BigSixNinePan pan69)
        {
            bool 陽日 = GJR.陰陽(pan69.日干) == e陰陽.陽;
            var 三傳 = pan69.三傳;
            String 干上神 = pan69.取上神(GJR.天干寄宮(pan69.日干));
            if (陽日)
            {
                三傳["初傳"].支神 = GJR.位移(干上神, 2);  //初為 第一課上神 next 2
                三傳["中傳"].支神 = 干上神;
                三傳["末傳"].支神 = 干上神;
            }
            else
            {
                //取第四課上神逆數3
                三傳["初傳"].支神 = GJR.位移(pan69.課[3].上神, -2);
                三傳["中傳"].支神 = 干上神;
                三傳["末傳"].支神 = 干上神;
            }
            if (三傳["初傳"].支神.Equals(三傳["中傳"].支神) && 三傳["初傳"].支神.Equals(三傳["末傳"].支神))
            {
                //獨足 只有己未日 第11課 出現 剛好三傳是 酉酉酉 
                pan69.addTransNote("獨足");
            }
        }

        protected int pick初傳From有剋(BigSixNinePan pan69, bool addNote = true)
        {
            var 賊課 = pan69.賊課();
            var 剋課 = pan69.剋課();
            int idx = -1;

            if (pan69.is23同())
            {
                賊課.Remove(2);
                剋課.Remove(2);
            }
            //八專..
            if (pan69.is24同())
            {
                賊課.Remove(3);
                剋課.Remove(3);
            }


            if (賊課.Count > 0)
            {
                if (賊課.Count == 1)
                {
                    if (剋課.Count == 0)
                    {
                        if (addNote)
                            pan69.addTransNote("始入");
                    }
                    else
                    {
                        if (addNote)
                            pan69.addTransNote("重審");
                    }
                    idx = 賊課[0];
                }
                else
                {
                    idx = pick初傳From比用涉害(pan69, 賊課);
                }
            }
            else
            {
                //只有剋
                if (剋課.Count == 1)
                {
                    pan69.addTransNote("元首");
                    idx = 剋課[0];
                }
                else
                {
                    idx = pick初傳From比用涉害(pan69, 剋課);
                }
            }
            return idx;

        }

        /*********************************************************************
         * 
         * 
         *********************************************************************/
        private int pick初傳From涉害(BigSixNinePan pan69, List<int> 賊剋課)
        {

            var 涉害 = new Dictionary<string, int>();
            var 課位 = new Dictionary<string, int>();
            pan69.addTransNote("涉害");

            List<Dictionary<String, Object>> 涉害統計 = new List<Dictionary<string, object>>();

            foreach (int idx in 賊剋課)
            {
                String 上神 = pan69.課[idx].上神;
                String from = pan69.取下神(上神);
                int 害數 = 0;
                if (pan69.課[idx].剋 == 賊剋.賊) //賊就是上面被剋
                    害數 = GJR.歷數歸於本家(from, 上神, false);
                else
                    害數 = GJR.歷數歸於本家(from, 上神, true);

                Dictionary<String, Object> r = new Dictionary<string, object>();
                r.Add("上神", 上神);
                r.Add("害數", 害數);
                r.Add("課位", idx);
                String posJi = pan69.課[idx].下神;
                if (GJR.isJi(posJi) == false)
                    posJi = GJR.天干寄宮(posJi);
                r.Add("地盤", posJi);
                r.Add("孟仲季", GJR.孟仲季(posJi));
                涉害統計.Add(r);
            }

            List<Dictionary<String, Object>> mylist = new List<Dictionary<string, object>>();
            mylist.AddRange(from p in 涉害統計 orderby p["害數"] descending select p);
            int max = (int)mylist[0]["害數"];
            while (true)
            {
                if ((int)mylist[mylist.Count - 1]["害數"] != max)
                    mylist.RemoveAt(mylist.Count - 1);
                else
                    break;
            }
            if (mylist.Count == 1)
            {

                return (int)mylist[0]["課位"];
            }
            mylist.Clear();
            mylist.AddRange(from p in 涉害統計 where max == (int)p["害數"] orderby p["孟仲季"] select p);

            if ((int)mylist[0]["孟仲季"] != (int)mylist[1]["孟仲季"])
            {
                int seq = (int)mylist[0]["孟仲季"];
                if (seq == 0)
                    pan69.addTransNote("見機");
                if (seq == 1)
                    pan69.addTransNote("查微");
                return (int)mylist[0]["課位"];
            };
            //取日干上神
            if (pan69.課[0].下神.Equals("戊") == false)
            {
                //throw new Exception("涉害有錯");
            }
            pan69.addTransNote("綴瑕");
            return 0;
        }
        private int pick初傳From比用涉害(BigSixNinePan pan69, List<int> 賊課)
        {
            String 日干 = pan69.日干;
            //重點是比用 ~~ 俱比,
            List<int> sameInYan = new List<int>();
            List<int> notsameInYan = new List<int>();

            foreach (int idx in 賊課)
            {
                String 上神 = pan69.課[idx].上神;
                if (GJR.陰陽(上神) == GJR.陰陽(日干))
                {
                    sameInYan.Add(idx);
                }
                else
                    notsameInYan.Add(idx);
            }
            if (sameInYan.Count == 0)
            {
                return pick初傳From涉害(pan69, notsameInYan);
            }
            if (sameInYan.Count == 1)
            {
                pan69.addTransNote("比用");
                return sameInYan[0];
            }
            if (sameInYan.Count == 2)
            {
                if (pan69.課[sameInYan[0]].上神.Equals(pan69.課[sameInYan[1]].上神))
                    return sameInYan[0];
                return pick初傳From涉害(pan69, sameInYan);
            }
            return pick初傳From涉害(pan69, sameInYan);
            /*File.WriteAllText(@"d:\2.txt", pan69.toJson(), Encoding.UTF8);
            throw new Exception("比用失敗 " + pan69.toJson());*/
        }

        protected void process返吟有剋(BigSixNinePan pan69)
        {
            int idx = pick初傳From有剋(pan69);
            pan69.發用課 = idx;
            String 初傳 = pan69.課[idx].上神;
            pan69.三傳["初傳"].支神 = 初傳;
            pan69.三傳["中傳"].支神 = GJR.沖(初傳); ;
            pan69.三傳["末傳"].支神 = 初傳;
            pan69.addTransNote("無依");
        }
        protected void process返吟(BigSixNinePan pan69)
        {
            pan69.addTransNote("返吟");
            if (pan69.has賊剋())
                process返吟有剋(pan69);
            else
                process返吟無剋(pan69);
        }

        private void process返吟無剋(BigSixNinePan pan69)
        {
            //辛,丁,己 vs 未丑
            String[] pat1 = { "辛未", "辛丑", "丁丑", "己丑" };
            String[] pat2 = { "丁未", "己未" };
            String 日干支 = pan69.日干支;
            //遇此四課無賊剋 以馬為用
            var 三傳 = pan69.三傳;
            if (pat1.Contains(日干支))
            {
                三傳["初傳"].支神 = GJR.驛馬(pan69.日支);
                三傳["中傳"].支神 = pan69.取上神(pan69.日支);
                三傳["末傳"].支神 = pan69.取上神(pan69.日干);
                pan69.addTransNote("無親");
                pan69.addTransNote("井欄射");
                return;
            }
            if (pat2.Contains(日干支))
            {
                三傳["初傳"].支神 = "巳";
                三傳["中傳"].支神 = pan69.取上神(pan69.日干);
                三傳["末傳"].支神 = pan69.取上神(pan69.日干);
                pan69.addTransNote("八專");
                return;
            }
            throw new Exception(" Invalid State process返吟無剋:" + JsonConvert.SerializeObject(pan69));

        }

        protected List<String> createSkySeq(String hourJi, String monGeneral)
        {
            int offset = GJR.JiId(monGeneral) - GJR.JiId(hourJi);
            if (offset < 0)
                offset += 12;
            return createSkySeq(offset);
        }
        protected List<String> createSkySeq(int offset)
        {
            List<String> result = new List<string>();
            for (int i = 0; i < 12; i++)
            {
                String ji = GJR.Id2Ji((offset + i) % 12);
                result.Add(ji);
            }
            return result;
        }

        public BigSixNinePan createPan(String dayGj, int offset)
        {
            List<String> sky = createSkySeq(offset);
            //貴人start ?
            return null;
        }






        protected List<String> calClass4Easy(String 日干支, List<String> sky)
        {
            String 日干 = 日干支.Substring(0, 1);
            String 日支 = 日干支.Substring(1, 1);

            List<String> result = new List<string>();
            String ji = GJR.天干寄宮(日干);
            String up = sky[GJR.JiId(ji) % 12];
            result.Add(up + 日干);
            result.Add(sky[GJR.JiId(up) % 12] + up);

            ji = 日支;
            up = sky[GJR.JiId(ji) % 12];
            result.Add(up + 日支);
            result.Add(sky[GJR.JiId(up) % 12] + up);
            return result;
        }
        protected void calClass4(BigSixNinePan pan)
        {
            List<String> result = new List<string>();
            String up = GJR.天干寄宮(pan.日干);
            result.Add(up + pan.日干);
            result.Add(pan.取上神(up) + up);
            up = pan.取上神(pan.日支);
            result.Add(up + pan.日支);
            result.Add(pan.取上神(up) + up);
            pan.setClass4(result);
        }


        public BigSixNinePan createPan(DateTime dt, int hr, int min)
        {
            String monthGeneral = JachiHelper.getMonthGeneral(dt);

            return null;
        }
        public BigSixNinePan createPan(DateTime dt, String ji)
        {
            String monthGeneral = JachiHelper.getMonthGeneral(dt);

            return null;
        }


        protected void update課傳天將(BigSixNinePan pan69)
        {
            String 日干 = pan69.日干;
            foreach (var 傳 in pan69.三傳.Values)
            {
                傳.天將 = pan69.天盤(傳.支神).天將;
            }
            foreach (var 課 in pan69.課)
            {
                課.天將 = pan69.天盤(課.上神).天將;
            }
        }
        private void process三傳六親(BigSixNinePan pan69)
        {
            String 日干 = pan69.日干;
            foreach (var 傳 in pan69.三傳.Values)
            {
                傳.六親 = GJR.六親AofB(傳.支神, 日干);
            }
            
        }
        protected void process三傳遁干(BigSixNinePan pan69)
        {
            String 日柱 = pan69.日干 + pan69.日支;

            bool 空亡 = false;
            foreach (var 傳 in pan69.三傳.Values)
            {
                傳.遁干 = process遁干(日柱, 傳.支神, out 空亡);
                if (空亡)
                    傳.空亡 = true;

            }
        }
        public String process遁干(String 干支, String 支神, out bool 空亡)
        {
            int diff = GJR.JiId(干支.Substring(1, 1)) - GJR.ganId(干支.Substring(0, 1));
            if (diff < 0)
                diff += 12;
            int id = GJR.JiId(支神);
            int ganid = (id - diff + 12) % 12;
            String 干神 = GJR.Id2Gan(ganid);
            if ((id == diff) || (id == (diff + 11) % 12))
            {
                空亡 = true;
            }
            空亡 = false;
            return 干神;
        }

    }
}
